In [1]:
Copied!
# %pip install geoai-py
# %pip install geoai-py
Import libraries¶
In [2]:
Copied!
import geoai
import geoai
Download sample data¶
In [3]:
Copied!
raster_url = (
"https://huggingface.co/datasets/giswqs/geospatial/resolve/main/naip_train.tif"
)
vector_url = "https://huggingface.co/datasets/giswqs/geospatial/resolve/main/naip_train_buildings.geojson"
raster_url = (
"https://huggingface.co/datasets/giswqs/geospatial/resolve/main/naip_train.tif"
)
vector_url = "https://huggingface.co/datasets/giswqs/geospatial/resolve/main/naip_train_buildings.geojson"
In [4]:
Copied!
raster_path = geoai.download_file(raster_url)
raster_path = geoai.download_file(raster_url)
naip_train.tif: 0%| | 0.00/12.1M [00:00<?, ?B/s]
naip_train.tif: 14%|█▍ | 1.68M/12.1M [00:00<00:00, 17.6MB/s]
naip_train.tif: 97%|█████████▋| 11.8M/12.1M [00:00<00:00, 69.6MB/s]
naip_train.tif: 100%|██████████| 12.1M/12.1M [00:00<00:00, 62.2MB/s]
In [5]:
Copied!
vector_path = geoai.download_file(vector_url)
vector_path = geoai.download_file(vector_url)
naip_train_buildings.geojson: 0%| | 0.00/456k [00:00<?, ?B/s]
naip_train_buildings.geojson: 100%|██████████| 456k/456k [00:00<00:00, 7.24MB/s]
Initialize building footprint extraction pretrained model¶
In [6]:
Copied!
extractor = geoai.BuildingFootprintExtractor()
extractor = geoai.BuildingFootprintExtractor()
Model path not specified, downloading from Hugging Face...
Model downloaded to: /home/runner/.cache/huggingface/hub/models--giswqs--geoai/snapshots/56c4c016f4a8eb4c51e5b5d6028c294ec90a445f/building_footprints_usa.pth Model loaded successfully
In [7]:
Copied!
mask_path = extractor.save_masks_as_geotiff(
raster_path=raster_path,
output_path="building_masks.tif",
confidence_threshold=0.5,
mask_threshold=0.5,
)
mask_path = extractor.save_masks_as_geotiff(
raster_path=raster_path,
output_path="building_masks.tif",
confidence_threshold=0.5,
mask_threshold=0.5,
)
Processing masks with parameters: - Confidence threshold: 0.5 - Chip size: (512, 512) - Mask threshold: 0.5 Dataset initialized with 3 rows and 5 columns of chips Image dimensions: 2503 x 1126 pixels Chip size: 512 x 512 pixels CRS: EPSG:26911
Processing raster with 4 batches
0%| | 0/4 [00:00<?, ?it/s]
25%|██▌ | 1/4 [00:12<00:36, 12.08s/it]
50%|█████ | 2/4 [00:23<00:23, 11.72s/it]
Resizing masks at image edges (set verbose=True for details)
75%|███████▌ | 3/4 [00:34<00:11, 11.44s/it]
100%|██████████| 4/4 [00:42<00:00, 10.10s/it]
100%|██████████| 4/4 [00:42<00:00, 10.68s/it]
Building masks saved to building_masks.tif
Convert raster to vector
In [8]:
Copied!
gdf = extractor.masks_to_vector(
mask_path=mask_path,
output_path="building_masks.geojson",
simplify_tolerance=1.0,
)
gdf = extractor.masks_to_vector(
mask_path=mask_path,
output_path="building_masks.geojson",
simplify_tolerance=1.0,
)
Converting mask to GeoJSON with parameters: - Mask threshold: 0.5 - Min building area: 100 - Simplify tolerance: 1.0 - NMS IoU threshold: 0.5 - Regularize buildings: True - Angle threshold: 15° from 90° - Rectangularity threshold: 70.0% Mask dimensions: (1126, 2503) Mask value range: 0 to 255 Found 642 potential buildings
0%| | 0/642 [00:00<?, ?it/s]
13%|█▎ | 81/642 [00:00<00:00, 805.22it/s]
25%|██▌ | 163/642 [00:00<00:00, 813.40it/s]
38%|███▊ | 245/642 [00:00<00:00, 808.03it/s]
51%|█████ | 326/642 [00:00<00:00, 805.22it/s]
63%|██████▎ | 407/642 [00:00<00:00, 806.23it/s]
76%|███████▌ | 488/642 [00:00<00:00, 802.56it/s]
89%|████████▊ | 569/642 [00:00<00:00, 798.53it/s]
100%|██████████| 642/642 [00:00<00:00, 806.19it/s]
Created 623 valid polygons
Building count after NMS filtering: 623 Regularizing 623 building footprints... - Angle threshold: 15° from 90° - Min orthogonality: 30.0% of angles - Min rectangularity: 70.0% of bounding box area
0%| | 0/623 [00:00<?, ?it/s]
22%|██▏ | 134/623 [00:00<00:00, 1338.09it/s]
43%|████▎ | 271/623 [00:00<00:00, 1348.06it/s]
66%|██████▌ | 411/623 [00:00<00:00, 1369.21it/s]
91%|█████████ | 564/623 [00:00<00:00, 1432.24it/s]
100%|██████████| 623/623 [00:00<00:00, 1422.85it/s]
INFO:pyogrio._io:Created 623 records
Regularization completed: - Total buildings: 623 - Rectangular buildings: 619 (99.4%) - Other regularized buildings: 0 (0.0%) - Unmodified buildings: 4 (0.6%) Saved 623 building footprints to building_masks.geojson
Option 2: Extract building footprints as vector¶
In [9]:
Copied!
output_path = "naip_buildings.geojson"
gdf = extractor.process_raster(
raster_path,
output_path="buildings.geojson",
batch_size=4,
confidence_threshold=0.5,
overlap=0.25,
nms_iou_threshold=0.5,
small_building_area=100,
mask_threshold=0.5,
simplify_tolerance=1.0,
)
output_path = "naip_buildings.geojson"
gdf = extractor.process_raster(
raster_path,
output_path="buildings.geojson",
batch_size=4,
confidence_threshold=0.5,
overlap=0.25,
nms_iou_threshold=0.5,
small_building_area=100,
mask_threshold=0.5,
simplify_tolerance=1.0,
)
Processing with parameters: - Confidence threshold: 0.5 - Tile overlap: 0.25 - Chip size: (512, 512) - NMS IoU threshold: 0.5 - Mask threshold: 0.5 - Min building area: 100 - Simplify tolerance: 1.0 - Filter edge buildings: True - Edge buffer size: 20 pixels Dataset initialized with 3 rows and 5 columns of chips Image dimensions: 2503 x 1126 pixels Chip size: 512 x 512 pixels CRS: EPSG:26911
Processing raster with 4 batches
0%| | 0/4 [00:00<?, ?it/s]
25%|██▌ | 1/4 [00:10<00:31, 10.64s/it]
50%|█████ | 2/4 [00:22<00:22, 11.12s/it]
75%|███████▌ | 3/4 [00:33<00:11, 11.16s/it]
100%|██████████| 4/4 [00:41<00:00, 9.94s/it]
100%|██████████| 4/4 [00:41<00:00, 10.34s/it]
INFO:pyogrio._io:Created 679 records
Buildings before filtering: 684 Buildings after filtering: 679 Saved 679 building footprints to buildings.geojson
Regularize building footprints¶
In [10]:
Copied!
gdf_regularized = extractor.regularize_buildings(
gdf=gdf,
min_area=100,
angle_threshold=15,
orthogonality_threshold=0.3,
rectangularity_threshold=0.7,
)
gdf_regularized = extractor.regularize_buildings(
gdf=gdf,
min_area=100,
angle_threshold=15,
orthogonality_threshold=0.3,
rectangularity_threshold=0.7,
)
Regularizing 679 building footprints... - Angle threshold: 15° from 90° - Min orthogonality: 30.0% of angles - Min rectangularity: 70.0% of bounding box area
0%| | 0/679 [00:00<?, ?it/s]
21%|██▏ | 145/679 [00:00<00:00, 1447.28it/s]
43%|████▎ | 292/679 [00:00<00:00, 1457.53it/s]
66%|██████▌ | 446/679 [00:00<00:00, 1493.31it/s]
88%|████████▊ | 596/679 [00:00<00:00, 1491.08it/s]
100%|██████████| 679/679 [00:00<00:00, 1493.85it/s]
Regularization completed: - Total buildings: 679 - Rectangular buildings: 648 (95.4%) - Other regularized buildings: 0 (0.0%) - Unmodified buildings: 31 (4.6%)
Visualize building footprints¶
In [11]:
Copied!
gdf.head()
gdf.head()
Out[11]:
| geometry | confidence | class | |
|---|---|---|---|
| 624 | POLYGON ((455181.6 5277618.6, 455177.4 5277614... | 0.994213 | 1 |
| 616 | POLYGON ((454990.2 5277628.2, 454990.2 5277627... | 0.992599 | 1 |
| 617 | POLYGON ((454855.8 5277628.2, 454855.8 5277626... | 0.989381 | 1 |
| 278 | POLYGON ((454981.8 5277798, 454981.2 5277797.4... | 0.986561 | 1 |
| 279 | POLYGON ((455052 5277904.8, 455050.8 5277903.6... | 0.982763 | 1 |
In [12]:
Copied!
geoai.view_vector_interactive(
gdf, column="confidence", layer_name="Building", tiles="Satellite"
)
geoai.view_vector_interactive(
gdf, column="confidence", layer_name="Building", tiles="Satellite"
)
Out[12]:
Make this Notebook Trusted to load map: File -> Trust Notebook
In [13]:
Copied!
geoai.view_vector_interactive(
gdf, column="confidence", layer_name="Building", tiles=raster_url
)
geoai.view_vector_interactive(
gdf, column="confidence", layer_name="Building", tiles=raster_url
)
Out[13]:
Make this Notebook Trusted to load map: File -> Trust Notebook
In [14]:
Copied!
geoai.view_vector_interactive(
gdf_regularized, column="confidence", layer_name="Building", tiles=raster_url
)
geoai.view_vector_interactive(
gdf_regularized, column="confidence", layer_name="Building", tiles=raster_url
)
Out[14]:
Make this Notebook Trusted to load map: File -> Trust Notebook
In [15]:
Copied!
extractor.visualize_results(raster_path, gdf, output_path="naip_buildings.png")
extractor.visualize_results(raster_path, gdf, output_path="naip_buildings.png")
Using confidence values (range: 0.50 - 0.99)
Visualization saved to naip_buildings.png
Sample visualization saved to naip_buildings_sample.png
In [16]:
Copied!
extractor.visualize_results(
raster_path, gdf_regularized, output_path="naip_buildings_regularized.png"
)
extractor.visualize_results(
raster_path, gdf_regularized, output_path="naip_buildings_regularized.png"
)
Using confidence values (range: 0.50 - 0.99)
Visualization saved to naip_buildings_regularized.png
Sample visualization saved to naip_buildings_regularized_sample.png